package org.freelunch.visitors;

import java.io.IOException;
import java.lang.reflect.Modifier;
import java.util.HashMap;
import java.util.List;

import org.apache.lucene.document.Document;
import org.apache.lucene.document.Field;
import org.apache.lucene.index.CorruptIndexException;
import org.apache.lucene.index.IndexWriter;

import japa.parser.ast.Comment;
import japa.parser.ast.CompilationUnit;
import japa.parser.ast.body.BodyDeclaration;
import japa.parser.ast.body.ClassOrInterfaceDeclaration;
import japa.parser.ast.body.ConstructorDeclaration;
import japa.parser.ast.body.FieldDeclaration;
import japa.parser.ast.body.MethodDeclaration;
import japa.parser.ast.body.Parameter;
import japa.parser.ast.body.TypeDeclaration;
import japa.parser.ast.body.VariableDeclarator;
import japa.parser.ast.expr.AnnotationExpr;
import japa.parser.ast.expr.ArrayAccessExpr;
import japa.parser.ast.expr.ArrayCreationExpr;
import japa.parser.ast.expr.ArrayInitializerExpr;
import japa.parser.ast.expr.AssignExpr;
import japa.parser.ast.expr.BinaryExpr;
import japa.parser.ast.expr.BooleanLiteralExpr;
import japa.parser.ast.expr.CastExpr;
import japa.parser.ast.expr.CharLiteralExpr;
import japa.parser.ast.expr.ClassExpr;
import japa.parser.ast.expr.ConditionalExpr;
import japa.parser.ast.expr.DoubleLiteralExpr;
import japa.parser.ast.expr.EnclosedExpr;
import japa.parser.ast.expr.Expression;
import japa.parser.ast.expr.FieldAccessExpr;
import japa.parser.ast.expr.InstanceOfExpr;
import japa.parser.ast.expr.IntegerLiteralExpr;
import japa.parser.ast.expr.IntegerLiteralMinValueExpr;
import japa.parser.ast.expr.LiteralExpr;
import japa.parser.ast.expr.LongLiteralExpr;
import japa.parser.ast.expr.LongLiteralMinValueExpr;
import japa.parser.ast.expr.MarkerAnnotationExpr;
import japa.parser.ast.expr.MemberValuePair;
import japa.parser.ast.expr.MethodCallExpr;
import japa.parser.ast.expr.NameExpr;
import japa.parser.ast.expr.NormalAnnotationExpr;
import japa.parser.ast.expr.NullLiteralExpr;
import japa.parser.ast.expr.ObjectCreationExpr;
import japa.parser.ast.expr.QualifiedNameExpr;
import japa.parser.ast.expr.SingleMemberAnnotationExpr;
import japa.parser.ast.expr.StringLiteralExpr;
import japa.parser.ast.expr.SuperExpr;
import japa.parser.ast.expr.ThisExpr;
import japa.parser.ast.expr.UnaryExpr;
import japa.parser.ast.expr.VariableDeclarationExpr;
import japa.parser.ast.stmt.AssertStmt;
import japa.parser.ast.stmt.BlockStmt;
import japa.parser.ast.stmt.BreakStmt;
import japa.parser.ast.stmt.CatchClause;
import japa.parser.ast.stmt.DoStmt;
import japa.parser.ast.stmt.ExpressionStmt;
import japa.parser.ast.stmt.ForStmt;
import japa.parser.ast.stmt.ForeachStmt;
import japa.parser.ast.stmt.IfStmt;
import japa.parser.ast.stmt.LabeledStmt;
import japa.parser.ast.stmt.Statement;
import japa.parser.ast.stmt.SwitchEntryStmt;
import japa.parser.ast.stmt.SwitchStmt;
import japa.parser.ast.stmt.SynchronizedStmt;
import japa.parser.ast.stmt.ThrowStmt;
import japa.parser.ast.stmt.TryStmt;
import japa.parser.ast.stmt.TypeDeclarationStmt;
import japa.parser.ast.stmt.WhileStmt;
import japa.parser.ast.type.ClassOrInterfaceType;
import japa.parser.ast.visitor.VoidVisitorAdapter;

public class MethodVisitor extends VoidVisitorAdapter implements MethodVisitorInterface {

	private HashMap<String, String> fields = new HashMap<String, String>();
	private HashMap<String, String> localVars = new HashMap<String, String>();
	
	private IndexWriter indexWriter;
	private CompilationUnit cut;

	// add assert to doc thts all!
	public void addAssertStatment(Statement st, Document doc, String name) {

		doc.add(new Field("Assert", name + "_" + st.toString() + "#"
				+ st.getBeginLine() + ">" + st.getEndLine(), Field.Store.YES,
				Field.Index.ANALYZED));

	}

	public void addBlockStatement(Statement st, Document doc, String name) {

		BlockStmt bstmt = (BlockStmt) st;
		if (bstmt.getStmts() != null)
			for (Statement stt : bstmt.getStmts()) {

				addStatement(stt, doc, name);

			}
	}

	public void addBreakStatement(Statement st, Document doc) {

	}

	public void addCatchClause(Statement st, Document doc, String name) {

		BlockStmt bs = (BlockStmt) st;
		addBlockStatement(bs, doc, name);
	}

	public void addContinue(Statement st, Document doc) {

	}

	public void addStatement(Statement st, Document doc, String name) {
		// DONE interpret statement
		if (st instanceof AssertStmt)
			addAssertStatment(st, doc, name);
		if (st instanceof BlockStmt)// find all meth calls inside block
			addBlockStatement(st, doc, name);
		if (st instanceof BreakStmt)
			;// no -op got better things to do :)
		if (st instanceof DoStmt)
			addDoStmt(st, doc, name);
		if (st instanceof ExpressionStmt)
			addExpressionStmt(st, doc, name);
		if (st instanceof ForeachStmt)
			addForEachStmt(st, doc, name);
		if (st instanceof ForStmt)
			addForStmt(st, doc, name);
		if (st instanceof IfStmt)
			addIfStmt(st, doc, name);
		if (st instanceof LabeledStmt)
			addLabelStmt(st, doc, name);
		if (st instanceof SwitchStmt)
			addSwitchStmt(st, doc, name);
		if (st instanceof SynchronizedStmt)
			addSynchronizedStmt(st, doc, name);
		if (st instanceof ThrowStmt)
			addThrowStmt(st, doc, name);
		if (st instanceof TryStmt)
			addTryStmt(st, doc, name);
		if (st instanceof TypeDeclarationStmt)
			addTypeDeclStmt(st, doc, name);
		if (st instanceof WhileStmt)
			addWhileStmt(st, doc, name);
	}

	public void addDoStmt(Statement st, Document doc, String name) {
		// DONE find all method calls inside DOStmt
		DoStmt dst = (DoStmt) st;
		Statement stt = dst.getBody();
		addStatement(stt, doc, name);
		Expression expr = dst.getCondition();
		addExpression(expr, doc, name);
	}

	private void addExpression(Expression expr, Document doc, String name) {

		if (expr instanceof AnnotationExpr)
			addAnnotationExpr(expr, doc, name);
		if (expr instanceof ArrayAccessExpr)
			addArrayAccessExpr(expr, doc, name);
		if (expr instanceof ArrayAccessExpr)
			addArrayAccessExpr(expr, doc, name);
		if (expr instanceof ArrayCreationExpr)
			addArrayCreationExpr(expr, doc, name);
		if (expr instanceof ArrayInitializerExpr)
			addArrayInitializerExpr(expr, doc, name);
		if (expr instanceof AssignExpr)
			addAssignExpr(expr, doc, name);
		if (expr instanceof BinaryExpr)
			addBinaryExpr(expr, doc, name);
		if (expr instanceof BooleanLiteralExpr)
			addBooleanLiteralExpr(expr, doc, name);
		if (expr instanceof CastExpr)
			addCastExpr(expr, doc, name);
		if (expr instanceof CharLiteralExpr)
			addCharLiteralExpr(expr, doc, name);
		if (expr instanceof ClassExpr)
			addClassExpr(expr, doc, name);
		if (expr instanceof ConditionalExpr)
			addConditionalExpr(expr, doc, name);
		if (expr instanceof DoubleLiteralExpr)
			addDoubleLiteralExpr(expr, doc, name);
		if (expr instanceof EnclosedExpr)
			addEnclosedExpr(expr, doc, name);
		if (expr instanceof FieldAccessExpr)
			addFieldAccessExpr(expr, doc, name);
		if (expr instanceof InstanceOfExpr)
			addinstaceOfExpr(expr, doc, name);
		if (expr instanceof IntegerLiteralExpr)
			addIntegerLiteralExpr(expr, doc, name);
		if (expr instanceof IntegerLiteralMinValueExpr)
			addIntegerLiteralMinValExpr(expr, doc, name);
		if (expr instanceof LiteralExpr)
			addLiteralExpr(expr, doc, name);
		if (expr instanceof LongLiteralExpr)
			addLongLiteralExpr(expr, doc, name);
		if (expr instanceof LongLiteralMinValueExpr)
			addLongLiteralMinValExpr(expr, doc, name);
		if (expr instanceof MarkerAnnotationExpr)
			addMarkerAnnoExpr(expr, doc, name);
		if (expr instanceof MethodCallExpr)
			addMethodCallExpr((MethodCallExpr)expr, doc, name);
		if (expr instanceof NameExpr)
			addNameExpr(expr, doc, name);
		if (expr instanceof NormalAnnotationExpr)
			addNormalAnnoExpr(expr, doc, name);
		if (expr instanceof NormalAnnotationExpr)
			addNormalAnnoExpr(expr, doc, name);
		if (expr instanceof NullLiteralExpr)
			addNullLiteralExpr(expr, doc, name);
		if (expr instanceof ObjectCreationExpr)
			addObjectCreationExpr(expr, doc, name);
		if (expr instanceof QualifiedNameExpr)
			addQualifiedNameExpr(expr, doc, name);
		if (expr instanceof SingleMemberAnnotationExpr)
			addSingleMemberAnnoExpr(expr, doc, name);
		if (expr instanceof StringLiteralExpr)
			addStringLiteralExpr(expr, doc, name);
		if (expr instanceof SuperExpr)
			addSuperExpr(expr, doc, name);
		if (expr instanceof ThisExpr)
			addThisExpr(expr, doc, name);
		if (expr instanceof UnaryExpr)
			addUnaryExpr(expr, doc, name);
		if (expr instanceof VariableDeclarationExpr)
			addVariableDeclExpr(expr, doc, name);

	}

	public void addExplicitConstructorInvocationStmt(Statement st, Document doc) {

	}

	public void addExpressionStmt(Statement st, Document doc, String name) {

		ExpressionStmt est = (ExpressionStmt) st;
		addExpression(est.getExpression(), doc, name);
	}

	public void addForEachStmt(Statement st, Document doc, String name) {
		ForeachStmt fes = (ForeachStmt) st;
		addExpression(fes.getIterable(), doc, name);
		addVariableDeclExpr(fes.getVariable(), doc, name);
		addStatement(fes.getBody(), doc, name);

	}

	public void addForStmt(Statement st, Document doc, String name) {

		ForStmt fst = (ForStmt) st;
		List<Expression> init = fst.getInit();
		List<Expression> updt = fst.getUpdate();

		if (updt != null)
			for (Expression exp : updt)
				addExpression(exp, doc, name);

		addStatement(fst.getBody(), doc, name);
		if (init != null)
			for (Expression exp : init)
				addExpression(exp, doc, name);

	}

	public void addIfStmt(Statement st, Document doc, String name) {
		IfStmt ifs = (IfStmt) st;
		addExpression(ifs.getCondition(), doc, name);
		addStatement(ifs.getElseStmt(), doc, name);
		addStatement(ifs.getThenStmt(), doc, name);

	}

	public void addLabelStmt(Statement st, Document doc, String name) {

		LabeledStmt lbst = (LabeledStmt) st;
		addStatement(lbst.getStmt(), doc, name);

	}

	public void addReturnStmt(Statement st, Document doc) {

	}

	public void addSwitchEntryStmt(Statement st, Document doc, String name) {

	}

	public void addSwitchStmt(Statement st, Document doc, String name) {
		SwitchStmt sst = (SwitchStmt) st;
		addExpression(sst.getSelector(), doc, name);
		if (sst.getEntries() != null)
			for (SwitchEntryStmt swst : sst.getEntries()) {
				addSwitchEntryStmt(swst, doc, name);
			}
	}

	public void addSynchronizedStmt(Statement st, Document doc, String name) {
		SynchronizedStmt sst = (SynchronizedStmt) st;
		addExpression(sst.getExpr(), doc, name);

	}

	public void addThrowStmt(Statement st, Document doc, String name) {
		ThrowStmt tst = (ThrowStmt) st;
		addExpression(tst.getExpr(), doc, name);

	}

	public void addTryStmt(Statement st, Document doc, String name) {
		TryStmt trs = (TryStmt) st;
		addBlockStatement(trs.getTryBlock(), doc, name);
		if (trs.getFinallyBlock() != null)
			addBlockStatement(trs.getFinallyBlock(), doc, name);
		if (trs.getCatchs() != null)
			for (CatchClause cc : trs.getCatchs()) {
				addCatchClause(cc.getCatchBlock(), doc, name);
			}

	}

	public void addTypeDeclStmt(Statement st, Document doc, String name) {
		// TypeDeclarationStmt dcs = (TypeDeclarationStmt)st;
		// TODO interpret what this meansv2
	}

	public void addWhileStmt(Statement st, Document doc, String name) {
		WhileStmt ws = (WhileStmt) st;
		addExpression(ws.getCondition(), doc, name);
		addStatement(ws.getBody(), doc, name);

	}

	public void addEmptyStmt(Statement st, Document doc) {

	}

	public void addAnnotationExpr(Expression expr, Document doc, String name) {
		// TODO add annotation expressionv2
		AnnotationExpr anoE = (AnnotationExpr) expr;

	}

	public void addArrayAccessExpr(Expression expr, Document doc, String name) {
		// TODO add Array Access Exprv2
		// no work here either?
	}

	public void addArrayCreationExpr(Expression expr, Document doc, String name) {
		// TODO add Araay creation exprv2
		ArrayCreationExpr ace = (ArrayCreationExpr) expr;

	}

	public void addArrayInitializerExpr(Expression expr, Document doc,
                                        String name) {
		// TODO add array init exprv2

	}

	public void addAssignExpr(Expression expr, Document doc, String name) {
		// TODO add assign exprv2
		AssignExpr ae = (AssignExpr) expr;
		addExpression(ae.getValue(), doc, name);
		addExpression(ae.getTarget(), doc, name);
	}

	public void addBinaryExpr(Expression expr, Document doc, String name) {
		// TODO add binary Exprv2
		BinaryExpr be = (BinaryExpr) expr;
		addExpression(be.getLeft(), doc, name);
		addExpression(be.getRight(), doc, name);
	}

	public void addBooleanLiteralExpr(Expression expr, Document doc, String name) {
		// TODO boolean literal exprv2
		BooleanLiteralExpr ble = (BooleanLiteralExpr) expr;

	}

	public void addCastExpr(Expression expr, Document doc, String name) {
		// TODO char exprv2
	}

	public void addCharLiteralExpr(Expression expr, Document doc, String name) {
		// TODO char lit exprv2
	}

	public void addClassExpr(Expression expr, Document doc, String name) {
		// TODO class exprv2
	}

	public void addConditionalExpr(Expression expr, Document doc, String name) {
		// done!
		ConditionalExpr ce = (ConditionalExpr) expr;
		addExpression(ce.getCondition(), doc, name);
		addExpression(ce.getElseExpr(), doc, name);
		addExpression(ce.getThenExpr(), doc, name);

	}

	public void addDoubleLiteralExpr(Expression expr, Document doc, String name) {
		// TODO double lit exprv2

	}

	public void addEnclosedExpr(Expression expr, Document doc, String name) {
		// done! enclosedExprs
		addExpression(((EnclosedExpr) expr).getInner(), doc, name);
	}

	public void addFieldAccessExpr(Expression expr, Document doc, String name) {
		// TODO Field Access Exprv2
	}

	public void addinstaceOfExpr(Expression expr, Document doc, String name) {
		// TODO instance of exprv2

	}

	public void addIntegerLiteralExpr(Expression expr, Document doc, String name) {
		// TODO intger lit exprv2
	}

	public void addIntegerLiteralMinValExpr(Expression expr, Document doc,
                                            String name) {
		// TODO interger literal Min Val Exprv2
	}

	public void addLiteralExpr(Expression expr, Document doc, String name) {
		// TODO literal exprv2
	}

	public void addLongLiteralExpr(Expression expr, Document doc, String name) {
		// TODO long lit. exprv2
	}

	public void addLongLiteralMinValExpr(Expression expr, Document doc,
                                         String name) {
		// TODO add long lit min val exprv2
	}

	public void addMarkerAnnoExpr(Expression expr, Document doc, String name) {
		// TODO add marker annot exprv2
	}

	public void addMemberValuePair(Expression expr, Document doc) {

	}

	public void addMethodCallExpr(MethodCallExpr expr, Document doc, String name) {


		List<Expression> args = expr.getArgs();

		doc.add(new Field("Method_" + expr.getName(), name, Field.Store.YES,
                Field.Index.ANALYZED));
        String arg ="";
		if (args != null){
			doc.add(new Field("Method_" + expr.getName() + "_len", new Integer(
					args.size()).toString(), Field.Store.YES,
					Field.Index.ANALYZED));
            //TODO ver1.1@ decide expression types to dig into var type
            for (Expression tpe : args)
                arg = arg + tpe.toString() + ",";


        }else
			doc.add(new Field("Method_" + expr.getName() + "_len", "0",
					Field.Store.YES, Field.Index.ANALYZED));
		doc.add(new Field("Method_" + expr.getName() + "_start", new Integer(expr
				.getBeginLine()).toString(), Field.Store.YES,
				Field.Index.ANALYZED));
		doc.add(new Field("Method_" + expr.getName() + "_scope", expr.getScope()
				.toString(), Field.Store.YES, Field.Index.ANALYZED));

		arg = arg.length() > 0 ?  arg.substring(0, arg.length()-1):"";
        
		doc.add(new Field("Method_" + expr.getName() + "_args", arg,
				Field.Store.YES, Field.Index.ANALYZED));

	}

	public void addNameExpr(Expression expr, Document doc, String name) {
		// TODO add name exprv2
	}

	public void addNormalAnnoExpr(Expression expr, Document doc, String name) {
		// TODO add normal anno exprv2
		NormalAnnotationExpr nae = (NormalAnnotationExpr) expr;

	}

	public void addNullLiteralExpr(Expression expr, Document doc, String name) {
		// TODO add null lit exprv2
	}

	public void addObjectCreationExpr(Expression expr, Document doc, String name) {
		// TODO obj creatv2
	}

	public void addQualifiedNameExpr(Expression expr, Document doc, String name) {
		// TODO add Qual Name Exprv2
	}

	public void addSingleMemberAnnoExpr(Expression expr, Document doc,
                                        String name) {
		// TODO add Single Memeber ANnov2
	}

	public void addStringLiteralExpr(Expression expr, Document doc, String name) {
		// TODO add string literal expr v2
	}

	public void addSuperExpr(Expression expr, Document doc, String name) {
		// TODO add super exprv2
		SuperExpr se = (SuperExpr) expr;
		addExpression(se.getClassExpr(), doc, name);
	}

	public void addThisExpr(Expression expr, Document doc, String name) {
		// TODO add this exprv2
		ThisExpr te = (ThisExpr) expr;
		addExpression(te.getClassExpr(), doc, name);
	}

	public void addUnaryExpr(Expression expr, Document doc, String name) {
		addExpression(((UnaryExpr) expr).getExpr(), doc, name);

	}

	public void addVariableDeclExpr(Expression expr, Document doc, String name) {
		// TODO add Var Declgv2
		VariableDeclarationExpr vde = (VariableDeclarationExpr) expr;
		if (vde.getVars() != null)
			for (VariableDeclarator vd : vde.getVars()) {

				addExpression(vd.getInit(), doc, name);
			}
	}

	public void addAnnotationDecl(TypeDeclaration typeDecl, Document doc) {

	}

	public void addAnnotationMemeberDecl(BodyDeclaration typeDecl, Document doc) {

	}

	public void addBodyDecl(TypeDeclaration typeDecl, Document doc) {

	}

	public void addClassOrInterfaceDecl(TypeDeclaration typeDecl, Document doc) {
		ClassOrInterfaceDeclaration cot = (ClassOrInterfaceDeclaration) typeDecl;
		// Add Class name
		doc.add(new Field("Class_Name", cot.getName(), Field.Store.YES,
				Field.Index.ANALYZED));
		switch (cot.getModifiers()) {
		case (Modifier.PUBLIC):
			doc.add(new Field("Class_Modifier", "Public", Field.Store.YES,
					Field.Index.ANALYZED));
			break;
		case (Modifier.PRIVATE):
			doc.add(new Field("Class_Modifier", "Private", Field.Store.YES,
					Field.Index.ANALYZED));
			break;
		default:
			doc.add(new Field("Class_Modifier", "Protected", Field.Store.YES,
					Field.Index.ANALYZED));
			break;
		}

		List<ClassOrInterfaceType> coi = cot.getImplements();
		if (coi != null)
			for (ClassOrInterfaceType coit : coi) {
				doc.add(new Field("Implements", coit.getName(),
						Field.Store.YES, Field.Index.ANALYZED));
			}

		List<ClassOrInterfaceType> coe = cot.getExtends();
		if (coe != null)
			for (ClassOrInterfaceType coet : coe) {
				doc.add(new Field("Extends", coet.getName(), Field.Store.YES,
						Field.Index.ANALYZED));
			}
		doc.add(new Field("Class_Start", new Integer(cot.getBeginLine())
				.toString(), Field.Store.YES, Field.Index.ANALYZED));
		doc.add(new Field("Class_End",
				new Integer(cot.getEndLine()).toString(), Field.Store.YES,
				Field.Index.ANALYZED));
		List<BodyDeclaration> bdc = cot.getMembers();
		if (bdc != null) {
			for (BodyDeclaration bDcl : bdc) {
				if (bDcl instanceof FieldDeclaration)
					addFieldDecl(bDcl, doc);
				if (bDcl instanceof ConstructorDeclaration)
					addConstructorDecl(bDcl, doc);
				if (bDcl instanceof MethodDeclaration)
					addMethodDecl(bDcl, doc,cot.getName());

			}
		}
	}

	// add constructor throws,params,start,end,modifier to doc
	public void addConstructorDecl(BodyDeclaration typeDecl, Document doc) {
		ConstructorDeclaration conDec = (ConstructorDeclaration) typeDecl;
		List<Parameter> paras = conDec.getParameters();
		String parass = "";
		if (paras != null)
			for (Parameter pam : paras)
				parass = parass + pam.getType().toString() + ",";
		parass = parass.length() > 0 ? parass.substring(0, parass.length() - 1)
				: "";

		switch (conDec.getModifiers()) {
		case (Modifier.PUBLIC):
			doc.add(new Field("Constructor_Params", "Public (" + parass + ")",
					Field.Store.YES, Field.Index.ANALYZED));
			break;
		case (Modifier.PRIVATE):
			doc.add(new Field("Constructor_Params", "Private (" + parass + ")",
					Field.Store.YES, Field.Index.ANALYZED));
			break;
		default:
			doc.add(new Field("Contructor_Params",
					"Protected (" + parass + ")", Field.Store.YES,
					Field.Index.ANALYZED));
			break;
		}

		List<NameExpr> names = conDec.getThrows();
		String nEx = "";
		if (names != null)
			for (NameExpr nexp : names)
				nEx = nEx + nexp.toString() + ",";
		nEx = nEx.length() > 0 ? nEx.substring(0, nEx.length() - 1) : "";
		doc.add(new Field("Contructor_Throws", nEx, Field.Store.YES,
				Field.Index.ANALYZED));

		doc.add(new Field("Contructor_Start",
				new Integer(conDec.getBeginLine()).toString(), Field.Store.YES,
				Field.Index.ANALYZED));
		doc.add(new Field("Contructor_End", new Integer(conDec.getEndLine())
				.toString(), Field.Store.YES, Field.Index.ANALYZED));

	}

	public void addEmptyMemeberDecl(BodyDeclaration typeDecl, Document doc) {

	}

	public void addEmptyTypeDecl(TypeDeclaration typeDecl, Document doc) {

	}

	public void addEnumConsDecl(BodyDeclaration typeDecl, Document doc) {

	}

	public void addEnumDecl(BodyDeclaration typeDecl, Document doc) {

	}

	// adding field name,type,start,end,modifier to doc
	public void addFieldDecl(BodyDeclaration typeDecl, Document doc) {
		FieldDeclaration fed = (FieldDeclaration) typeDecl;
		List<VariableDeclarator> list = fed.getVariables();
		if (list != null) {
			for (VariableDeclarator vdi : list) {
				doc.add(new Field("Field_Name", vdi.getId().toString(),
						Field.Store.YES, Field.Index.ANALYZED));
				doc.add(new Field("Field_Type", fed.getType().toString(),
						Field.Store.YES, Field.Index.ANALYZED));
				switch (fed.getModifiers()) {
				case (Modifier.PUBLIC):
					doc.add(new Field("Field_Modifier", "Public "
							+ vdi.getId().toString(), Field.Store.YES,
							Field.Index.ANALYZED));
					break;
				case (Modifier.PRIVATE):
					doc.add(new Field("Field_Modifier", "Private "
							+ vdi.getId().toString(), Field.Store.YES,
							Field.Index.ANALYZED));
					break;
				default:
					doc.add(new Field("Field_Modifier", "Protected "
							+ vdi.getId().toString(), Field.Store.YES,
							Field.Index.ANALYZED));
					break;
				}

				fields.put(vdi.getId().toString(), fed.getType().toString());

			}
		}
		doc.add(new Field("Field_Start", new Integer(fed.getBeginLine())
				.toString(), Field.Store.YES, Field.Index.ANALYZED));
		doc.add(new Field("Field_End",
				new Integer(fed.getEndLine()).toString(), Field.Store.YES,
				Field.Index.ANALYZED));

	}

	public void addInitializerDecl(BodyDeclaration typeDecl, Document doc) {

	}

	public void addJavaDocComment(Comment typeDecl, Document doc) {

	}

	// add method name,modifier,throws,params,start and end in primiary Doc and
	// internalVars, internalStmtBlock in internalDoc
	public void addMethodDecl(BodyDeclaration typeDecl, Document doc, String name) {
		MethodDeclaration methD = (MethodDeclaration) typeDecl;
		List<Parameter> paras = methD.getParameters();
		String parass = "";
		if (paras != null)
			for (Parameter pam : paras)
				parass = parass + pam.getType().toString() + ",";
		parass = parass.length() > 0 ? parass.substring(0, parass.length() - 1)
				: "";
		List<NameExpr> names = methD.getThrows();
		String nEx = "";
		if (names != null)
			for (NameExpr nexp : names)
				nEx = nEx + nexp.toString() + ",";
		nEx = nEx.length() > 0 ? nEx.substring(0, nEx.length() - 1) : "";

		switch (methD.getModifiers()) {
		case (Modifier.PUBLIC):
			doc.add(new Field(name+".Method_full", "public " + methD.getName() + " ("
					+ parass + ") throws " + nEx + " #"
					+ new Integer(methD.getBeginLine()).toString() + ">"
					+ new Integer(methD.getEndLine()).toString(),
					Field.Store.YES, Field.Index.ANALYZED));
			break;
		case (Modifier.PRIVATE):
			doc.add(new Field(name+".Method_full", "private " + methD.getName() + " ("
					+ parass + ") throws " + nEx + " #"
					+ new Integer(methD.getBeginLine()).toString() + ">"
					+ new Integer(methD.getEndLine()).toString(),
					Field.Store.YES, Field.Index.ANALYZED));
			break;
		default:
			doc.add(new Field(name+".Method", "protected " + methD.getName() + " ("
					+ parass + ") throws " + nEx + " #"
					+ new Integer(methD.getBeginLine()).toString() + ">"
					+ new Integer(methD.getEndLine()).toString(),
					Field.Store.YES, Field.Index.ANALYZED));
			break;
			

		}
		//doc.add(new Field(name+".Method",));

		Document doc2 = new Document();
		BlockStmt bStmt = methD.getBody();
		List<Statement> Lst = bStmt.getStmts();
		if (Lst != null) {
			for (Statement st : Lst) {
				addStatement(st, doc2,cut.getPackage().getName()+"."+name+"."+methD.getName());
			}

		}
		try {
			if (doc2 != null)
				indexWriter.addDocument(doc2);
		} catch (CorruptIndexException e) {

			e.printStackTrace();
		} catch (IOException e) {

			e.printStackTrace();
		}

	}

	public void addModifierSet(TypeDeclaration typeDecl, Document doc) {

	}

	public void addTypeParameter(Document doc) {

	}

	public void addPackageDeclaration(Document doc) {

	}

	public void addImportDecl(Document doc) {

	}

	public void addCompilationUnit(Document doc) {

	}

	public void visit(CompilationUnit cu, IndexWriter indexWriter,
                      String absolutePath) {
		this.indexWriter = indexWriter;
		Document doc = new Document();
		cut=cu;

		if (cu.getTypes() != null)
			for (TypeDeclaration td : cu.getTypes()) {
				if (((ClassOrInterfaceDeclaration) td).isInterface())
					continue; // fuh-get interfaces ..they are nothing but
								// cosmetic 4me:) don't make me think harder
				if (td instanceof ClassOrInterfaceDeclaration) {
					addClassOrInterfaceDecl(td, doc);
				}
				if (td.getMembers() == null)
					continue;
				for (BodyDeclaration bdy : td.getMembers()) {
					if (bdy instanceof ConstructorDeclaration) {
						ConstructorDeclaration consDec = (ConstructorDeclaration) bdy;

						// 00h constructors could either be public/private or
						// protected or nothing wherein former falls
						switch (consDec.getModifiers()) {
						case (Modifier.PUBLIC):
							doc.add(new Field("Modifier", "Public",
									Field.Store.YES, Field.Index.NOT_ANALYZED));
							break;
						case (Modifier.PRIVATE):
							doc.add(new Field("Modifier", "Private",
									Field.Store.YES, Field.Index.NOT_ANALYZED));
							break;
						default:
							doc.add(new Field("Modifier", "Protected",
									Field.Store.YES, Field.Index.NOT_ANALYZED));
							break;

						}
						doc.add(new Field("StartLine", new Integer(consDec
								.getBeginLine()).toString(), Field.Store.YES,
								Field.Index.NOT_ANALYZED));
						doc.add(new Field("EndLine", new Integer(consDec
								.getEndLine()).toString(), Field.Store.YES,
								Field.Index.NOT_ANALYZED));
						if (consDec.getThrows() != null)
							for (NameExpr xpr : consDec.getThrows()) {
								doc.add(new Field("Throws", xpr.getName(),
										Field.Store.YES,
										Field.Index.NOT_ANALYZED));

							}
						String param = "";
						HashMap<String, String> parName = new HashMap<String, String>();
						if (consDec.getParameters() != null)
							for (japa.parser.ast.body.Parameter par : consDec
									.getParameters()) {
								doc.add(new Field("Type", par.getType()
										.toString(), Field.Store.YES,
										Field.Index.NOT_ANALYZED));
								doc.add(new Field("Param", par.toString(),
										Field.Store.YES,
										Field.Index.NOT_ANALYZED));
								int x = par.toString().indexOf(' ');
								parName.put(
										par.toString().substring(x,
												par.toString().length()), par
												.getType().toString());

							}
						BlockStmt bst = consDec.getBlock();
						if (bst != null)
							if (bst.getStmts() != null)
								for (Statement st : bst.getStmts()) {
									if (st instanceof ExpressionStmt) {
										ExpressionStmt tds = (ExpressionStmt) st;
										Expression exp = tds.getExpression();

										if (exp instanceof VariableDeclarationExpr) {
											if (((VariableDeclarationExpr) exp)
													.getVars() != null)
												for (VariableDeclarator vd : ((VariableDeclarationExpr) exp)
														.getVars())
													parName.put(
															vd.getId()
																	.toString(),
															((VariableDeclarationExpr) exp)
																	.getType()
																	.toString());

										}
										if (exp instanceof MethodCallExpr) {
											// doc.add(new Field("Scope"))
											// param.((MethodCallExpr)
											// exp).getScope()
										}
									}
								}

					}
				}

			}
		try {
			indexWriter.addDocument(doc);
			indexWriter.commit();

		} catch (CorruptIndexException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}

	}

}
